#include "my_define.h"
#include "my_can.h"
#include <string.h>
#include "flash_rw.h"
/*
校验和检查
*/
uint8_t ChackSum(uint8_t *data, uint8_t l)
{
    uint8_t sum = 0;
    for (size_t i = 0; i < l - 1; i++)
    {
        sum += data[i];
    }

    if (sum == data[l - 1])
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void CanBroadcasting()
{
    uint8_t info[8] = {0, 0, 0, 0, 0, 0, 0, 0};

    uint32_t canid = 0x700;

    FLOOR_INFO *f = &thisfloor;
    info[0] = thisfloor.id;

    info[1] = f->state.Button | f->state.InfraredDetection << 1;

    info[2] = f->state.AmbientLightLevel & 0xff;
    info[3] = f->state.AmbientLightLevel >> 8 & 0xff;

    info[4] = f->state.LightOutLevel & 0xff;
    info[5] = f->state.LightOutLevel >> 8 & 0xff;

    info[6] = f->state.cnt & 0xff;
    info[7] = f->state.cnt >> 8 & 0xff;

    vApp_CAN_TxMessage(&hcan, &can_TxHeader, canid, info, 8);
}

void CanSendRef()
{
    uint8_t info[8] = {0, 0, 0, 0, 0, 0, 0, 0};

    uint32_t canid = 0x704;

    FLOOR_INFO *f = &thisfloor;
    info[0] = f->id;

    info[1] = f->ref.lowlight & 0xff;
    info[2] = f->ref.lowlight >> 8 & 0xff;

    info[3] = f->ref.timeout & 0xff;
    info[4] = f->ref.timeout >> 8 & 0xff;

    for (size_t i = 0; i < 5; i++)
    {
        info[5] += info[i];
    }

    vApp_CAN_TxMessage(&hcan, &can_TxHeader, canid, info, 6);
}

/*
从can总线更新其他楼层参数
*/
uint8_t refflag = 0;
uint8_t refid;
FLOOR_REF refTemp;
void UpdateOrtherFloorRef(uint8_t *data, uint8_t l)
{
    //更新其他楼层状态信息
    if (ChackSum(data, l))
    {
        refid = data[0];
        refTemp.lowlight = *(uint16_t *)&data[1];
        refTemp.timeout = *(uint16_t *)&data[3];
        refflag = 1;
    }
}

/*
从can总线更新其他楼层信息
*/
void UpdateOrtherFloorState(uint8_t *data, uint8_t l)
{
    //更新其他楼层状态信息
    if (data[0] < MAXFLOOR && data[0] != thisfloor.id)
    {
        OTHER_STATE *f = &otherfloor[data[0]];
        f->state.Button = data[1] & 0x01;
        f->state.InfraredDetection = (data[1] >> 1) & 0x01;

        f->state.AmbientLightLevel = *(uint16_t *)&data[2];

        f->state.LightOutLevel = *(uint16_t *)&data[4];

        f->state.cnt = *(uint16_t *)&data[6];

        f->onlinecnt = 0;
    }
}

/*
强制控制*************************
*/
void ControlLED(uint8_t *data, uint8_t l)
{
    if (ChackSum(data, l))
    {
        if (data[0] == thisfloor.id) //响应本楼层控制参数
        {
            thisfloor.state.ControlLevel = *(uint16_t *)&data[1];
            thisfloor.state.ControlCnt = 0;
        }
    }
}
void CAN_ControlOther(uint8_t id, uint16_t level)
{
    uint8_t info[8] = {0, 0, 0, 0, 0, 0, 0, 0};

    uint32_t canid = 0x100;

    info[0] = id;

    info[1] = level & 0xff;
    info[2] = level >> 8 & 0xff;

    for (size_t i = 0; i < 3; i++)
    {
        info[3] += info[i];
    }
    vApp_CAN_TxMessage(&hcan, &can_TxHeader, canid, info, 4);
}
void Processing_CAN1(CAN_RxHeaderTypeDef can_RxHeader, uint8_t *can_RxData)
{
    static uint32_t id = 0;
    static uint8_t L = 0;
    static uint8_t buff[8];
    //static uint8_t state = 0x05;

    //立刻暂存数据，防止被新数据覆盖
    id = can_RxHeader.StdId;
    L = can_RxHeader.DLC;
    memcpy(buff, can_RxData, 8);

    //打印数据
#ifdef CAN_DEBUG

    printf("id=%x", id);
    printf("[");
    for (size_t i = 0; i < L; i++)
    {
        printf("%X ", buff[i]);
    }
    printf("]\n");
#endif
    switch (id)
    {
    case 0x700: //其他楼层广播数据
    {
        UpdateOrtherFloorState(buff, L);
    }
    break;
    case 0x704: //其他楼层参数数据
    {
        UpdateOrtherFloorRef(buff, L);
    }
    break;
    default:
        break;
    }
    if (id == 0x100)
    {
        ControlLED(buff, L);
    }
    //设置参数******************************
    if (id == (0x400 | thisfloor.id))
    {
        if (ChackSum(buff, L))
        {
            if (L == 2 && buff[0] == 0x00) //请求参数
            {
                CanSendRef();
            }
            if (L == 3 && buff[0] == 0x44) //修改id
            {
                ChangeID(buff[1]);
            }
            if (L == 6 && buff[0] == 0x01) //修改参数
            {
                thisfloor.ref.lowlight = *(uint16_t *)&buff[1];
                thisfloor.ref.timeout = *(uint16_t *)&buff[3];

                FLASH_FloorInfoSave(thisfloor.id, thisfloor.ref.lowlight, thisfloor.ref.timeout);
            }
        }
    }
}
/*
通过can总线读取其他设备参数
*/
uint8_t CAN_GetRef(uint8_t id, FLOOR_REF *ref)
{
    refflag = 0;
    uint8_t info[2] = {0, 0};
    uint32_t senid = 0x400 | id;
    for (size_t j = 0; j < 3; j++)
    {
        vApp_CAN_TxMessage2(&hcan, &can_TxHeader, senid, info, 2);
        for (size_t i = 0; i < 1000; i++)
        {
            HAL_Delay(1);
            if (refflag)
            {
                j = 5;
                break;
            }
        }
    }

    printf("id= %d refid=%d refflag = %d\n", id, refid, refflag);
    if (refid == id && refflag)
    {
        *ref = refTemp;
        return 1;
    }
    return 0;
}

uint8_t CAN_Setid(uint8_t id, uint8_t newid)
{
    uint8_t info[3] = {0x44, newid, 0};
    uint32_t senid = 0x400 | id;
    info[2] = info[0] + info[1];
    vApp_CAN_TxMessage(&hcan, &can_TxHeader, senid, info, 3);
    return 1;
}
void CAN_SetRef(uint8_t id, FLOOR_REF ref)
{

    uint8_t info[6];
    uint32_t senid = 0x400 | id;

    info[0] = 0x01;

    info[1] = ref.lowlight & 0xff;
    info[2] = ref.lowlight >> 8 & 0xff;

    info[3] = ref.timeout & 0xff;
    info[4] = ref.timeout >> 8 & 0xff;

    info[5] = 0;
    for (size_t i = 0; i < 5; i++)
    {
        info[5] += info[i];
    }

    vApp_CAN_TxMessage(&hcan, &can_TxHeader, senid, info, 6);

    // HAL_Delay(1);

    // info[0] = 0;
    // info[1] = 0;

    // refflag = 0;
    // vApp_CAN_TxMessage(&hcan, &can_TxHeader, senid, info, 2);
    // HAL_Delay(1);
    // if (refid == id && refflag)
    // {
    //     if (ref.lowlight == refTemp.lowlight && refTemp.timeout == ref.timeout)
    //         return 1;
    // }
    // return 0;
}
